//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : Container
// 文件名   : TestSet.h
// 作者     : Aiye
// 日期     : 2025/9/4 22:20
// 邮箱     : 2878548868@qq.com
// 摘要     : 介绍set
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CONTAINER_TESTSET_H
#define CONTAINER_TESTSET_H
#include <iostream>
#include <set>
#include <vector>

/**
 * @brief 介绍集合
 */
class TestSet
{
public:
    /**
     * @brief 介绍构造函数
     */
    static void TestConstuctor()
    {
        std::set<int> nSet{}; // 默认按照升序排列
        std::set<int , std::greater<>> nSet1{}; // 按照降序排列
        std::vector<int> nVec{1,2,3,4,5,2,2,1}; // 初始化列表构造
        std::set<int> nSet3(nVec.begin() , nVec.end()); // 重复元素会被忽略
        auto nSet4{nSet3}; // 拷贝构造，深拷贝
        auto nSet5{std::move(nSet4)}; // 移动构造函数
    }

    static void TestCapacity()
    {
        std::set<int> nSet{1,2,3,4,5};
        std::cout << "Size: " << nSet.size() << std::endl; // 获取元素数量
        std::cout << "Empty: " << nSet.empty() << std::endl; // 判空
        // set不存在capacity、reverse等操作
    }

    /**
     * @brief 元素访问
     */
    static void TestInterviews()
    {
        std::set<int> mySet = {1, 2, 3, 4, 5};

        // set不支持[]运算符，因为没有键值对的概念
        // mySet[0]; // 错误

        // 但是可以通过迭代器访问元素
        auto it = mySet.find(3);
        if (it != mySet.end())
        {
            std::cout << "Element found: " << *it << std::endl;
        }

        // 获取第一个元素（最小的元素）
        if (!mySet.empty())
        {
            std::cout << "First element: " << *mySet.begin() << std::endl;
        }

        // 获取最后一个元素（最大的元素）
        if (!mySet.empty())
        {
            std::cout << "Last element: " << *mySet.rbegin() << std::endl;
        }
    }

    static void TestAdd()
    {
        std::set<int> mySet;

        // 使用insert()插入元素
        auto result1 = mySet.insert(1);
        // result1是一个pair<iterator, bool>，iterator指向插入的元素，bool表示是否成功插入（即元素是否已存在）

        // 使用insert()带有提示位置的版本
        auto hint = mySet.begin();
        mySet.insert(hint, 2); // 提示位置，可能提高插入效率

        // 使用emplace()直接构造元素（C++11）
        auto result2 = mySet.emplace(3);

        // 使用emplace_hint()带提示位置的构造（C++11）
        mySet.emplace_hint(mySet.end(), 4);

        // 插入多个元素（C++11）
        mySet.insert({5, 6, 7});
    }

    static void TestDelete()
    {
        std::set<int> mySet = {1, 2, 3, 4, 5, 6, 7, 8, 9};

        // 通过键删除元素
        size_t count = mySet.erase(3); // 返回删除的元素数量（0或1）

        // 通过迭代器删除元素
        auto it = mySet.find(2);
        if (it != mySet.end())
        {
            mySet.erase(it);
        }

        // 删除一个范围内的元素
        auto first = mySet.find(4);
        auto last = mySet.find(7);
        mySet.erase(first, last); // 删除从4到7之前的所有元素（包括4，不包括7）

        // 删除所有元素
        mySet.clear();
    }

    static void TestFind()
    {
        std::set<int> mySet = {1, 2, 3, 4, 5, 6, 7, 8, 9};

        // 使用find()查找元素
        auto it = mySet.find(5);
        if (it != mySet.end())
        {
            std::cout << "Found: " << *it << std::endl;
        }

        // 使用count()检查元素是否存在（返回0或1）
        if (mySet.count(4) > 0)
        {
            std::cout << "Element 4 exists" << std::endl;
        }

        // 使用lower_bound()和upper_bound()进行范围查找
        // 查找所有大于等于3且小于7的元素
        auto low = mySet.lower_bound(3);
        auto up = mySet.upper_bound(7);
        for (auto it = low; it != up; ++it)
        {
            std::cout << *it << " ";
        }
        std::cout << std::endl;

        // 使用equal_range()获取匹配元素的范围（返回一个pair<iterator, iterator>）
        auto range = mySet.equal_range(5);
        for (auto it = range.first; it != range.second; ++it)
        {
            std::cout << *it << " "; // 由于set元素唯一，所以范围最多一个元素
        }
        std::cout << std::endl;
    }

    static void TestModifaction()
    {
        std::set<int> nSet{1,2,3,4,4,5};

        // 不能直接修改set中的值，因为所有元素的值都是const的
        // 正确的方法是先删除再插入
        auto it  = nSet.find(3); //
        if (it != nSet.end())
        {
            nSet.erase(it); // 删除
            nSet.insert(10); // 插入
        }

        // 或者使用extract方法
#ifdef __cpp_lib_node_extract
        auto node = nSet.extract(2); // 提取出节点
        if (!node.empty())
        {
            node.value() = 20;
            nSet.insert(std::move(node)); // 转移
        }
#endif
    }

    static void TestIterator()
    {
        std::set<int> mySet = {1, 2, 3, 4, 5};

        // 正向迭代
        std::cout << "Forward iteration:" << std::endl;
        for (auto it = mySet.begin(); it != mySet.end(); ++it)
        {
            std::cout << *it << " ";
        }
        std::cout << std::endl;

        // 反向迭代
        std::cout << "Reverse iteration:" << std::endl;
        for (auto it = mySet.rbegin(); it != mySet.rend(); ++it)
        {
            std::cout << *it << " ";
        }
        std::cout << std::endl;

        // 常量迭代器（防止修改）
        std::cout << "Const iteration:" << std::endl;
        for (auto it = mySet.cbegin(); it != mySet.cend(); ++it)
        {
            // *it = 10; // 错误：不能通过常量迭代器修改元素
            std::cout << *it << " ";
        }
        std::cout << std::endl;

        // 基于范围的for循环（C++11）
        std::cout << "Range-based for loop:" << std::endl;
        for (const auto& elem : mySet)
        {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }
};
#endif //CONTAINER_TESTSET_H